package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;
import com.hmdp.exception.WebException;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.MailUtil;
import com.hmdp.utils.PasswordEncoder;
import com.hmdp.utils.RegexUtils;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static com.hmdp.utils.RedisConstants.*;
import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;

;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private final StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean sendCode(String email, HttpSession session) {

        log.debug("接收到的邮箱" + email);
        if (RegexUtils.isEmailInvalid(email)) {
            throw new WebException("邮箱格式错误！");
        }

        String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + email);
        if (StringUtils.hasText(cacheCode)) {
            Long expire = stringRedisTemplate.getExpire(LOGIN_CODE_KEY + email);
            if (expire != null && LOGIN_CODE_TTL - expire < 60) {
                throw new WebException("请稍后重试");
            }
        }

        String code = RandomUtil.randomNumbers(6);
        MailUtil.sendMail(email, "黑马点评验证码：" + code + "，有效期为5分钟");
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + email, code, LOGIN_CODE_TTL, TimeUnit.MINUTES);
        return true;
    }

    @Override
    public String loginUser(LoginFormDTO loginForm, HttpSession session) {
        String email = loginForm.getPhone();
        String password = loginForm.getPassword();
        String code = loginForm.getCode();

        // 1. 校验邮箱格式
        if (RegexUtils.isEmailInvalid(email)) {
            throw new WebException("邮箱格式错误，请重新输入！");
        }

        // 2. 查询用户
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", email);
        User user = super.getOne(queryWrapper);

        // 3. 验证码登录逻辑
        if (StringUtils.hasText(code)) {
            if (RegexUtils.isCodeInvalid(code)) {
                throw new WebException("验证码格式错误");
            }
            //  获取缓存中的验证码
            String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + email);
            if (!code.equals(cacheCode)) {
                throw new WebException("验证码错误，请输入正确的验证码");
            }

            // 如果用户不存在，自动注册
            if (user == null) {
                user = new User();
                user.setPhone(email);
                user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));
                super.save(user);
            }
            return saveUserToCache(user);
        }

        // 4. 密码登录逻辑
        if (StringUtils.hasText(password)) {
            if (user == null) {
                // 新用户注册
                user = new User();
                user.setPhone(email);
                user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));
                user.setPassword(PasswordEncoder.encode(password));
                super.save(user);
            } else {
                // 校验密码
                if (!PasswordEncoder.matches(password, user.getPassword())) {
                    throw new WebException("密码错误");
                }
            }
            return saveUserToCache(user);
        }

        // 5. 输入不完整
        throw new WebException("请输入完整信息");
    }

    private String saveUserToCache(User user) {
        String token = UUID.randomUUID().toString(true);
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);

        Map<String, Object> userMap = new HashMap<>();
        userMap.put("id", user.getId() == null ? "" : user.getId().toString());
        userMap.put("nickName", user.getNickName() == null ? "" : user.getNickName());
        userMap.put("icon", user.getIcon() == null ? "" : user.getIcon());

        stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY + token, userMap);
        stringRedisTemplate.expire(LOGIN_USER_KEY + token, LOGIN_USER_TTL, TimeUnit.MINUTES);
        return token;
    }
}
